package a09_JUC;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @Author quan
 * @Description 演示ReentrantLock的不同方法
 * @Date 2023/5/15 17:01
 */
public class a03_ReentrantLock {
    /**
     * 演示reentrantLock的基本方法
     * @throws InterruptedException
     */
    public static void demo01_lock() throws InterruptedException {
        //1、创建一个ReentrantLock对象
        ReentrantLock reentrantLock = new ReentrantLock();
        //2、加锁
        reentrantLock.lock();
        //3、尝试加锁：死等
        reentrantLock.tryLock();
        //尝试加锁，有超时时间
        reentrantLock.tryLock(1, TimeUnit.SECONDS);
        //4、释放锁
        reentrantLock.unlock();
    }

    /**
     * 演示业务中如果出现异常，如何释放锁
     * @throws Exception
     */
    public static void demo2_exception() throws Exception {
        //1、创建一个ReentrantLock对象
        ReentrantLock reentrantLock = new ReentrantLock();
        //2、加锁
        reentrantLock.lock();
        //3、尝试执行并处理异常
        try {
            //TODO:要做的事情，业务逻辑
            throw new Exception("业务出现异常");
        }finally {
            //4、保证出现异常的时候也可以释放锁
            reentrantLock.unlock();
        }
    }

    /**
     * 演示创建公平锁
     */
    public static void demo3_fairLock(){
        //通过构造方法，传入true时表示为公平锁;传入false表示为非公平锁。默认状态下为false。
        ReentrantLock reentrantLock = new ReentrantLock(true);
    }

    /**
     * 演示创建读写锁
     */
    public static void demo4_ReadAndWriteLock(){
        //1、创建读写锁对象
        ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
        //2、获取读锁：读锁是共享锁，读和读可以同时进行
        readWriteLock.readLock();
        //3、获取写锁：写锁是排它锁，读写，写写，写读不能共存
        readWriteLock.writeLock();
    }

    /**
     * ReentrantLock可以根据不同的Condition去休眠或唤醒线程
     * 同一把锁可以分为不同的休眠或唤醒条件
     */
    //1、定义对象
    private static ReentrantLock reentrantLock = new ReentrantLock();
    //2、定义不同的条件：此处按照性别定义
    private static Condition boyCondition = reentrantLock.newCondition();
    private static Condition girlCondition = reentrantLock.newCondition();
    public static void demo5_Condition(){
        Thread thread1 = new Thread(()->{
            //3、让处理男生任务的线程去休眠
            try {
                boyCondition.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //3、唤醒处理女生任务的线程
            girlCondition.signalAll();
        });
        //4、让处理女生任务的线程去休眠，唤醒处理男生任务的线程
        Thread thread2 = new Thread(()->{
            try {
                girlCondition.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            boyCondition.signalAll();
        });
    }
}
